/* 
 * File:   render.cpp
 * Author: Thomas Trojer
 *
 * Created on 21. Oktober 2010, 23:14
 */

#include "types/Vec3.h"
#include "VerticesWatcher.h"
#include "RoutePlanner.h"
#include "TurtleState.h"
#include "Turtle.h"
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
#include <stdlib.h>
#include <math.h>

RoutePlanner route;
VerticesWatcher watcher;
string meal;

//angle of rotation
float xpos = -10, ypos = 10, zpos = -10, xrot = 0, yrot = 0, angle = 0.0;
float lastx, lasty;

void init(void) {
    meal = "A";
    route.rule("A -> [^(20)FA]/(125)[^(20)FA]/(125)[^(20)FA]");
    route.rule("F -> /(125)F");
    route.rule("S -> F");

    /*meal = "F";
    route.rule("F -> ^(90)/(90)F");*/
}

void iterate() {
    Turtle t(route);
    t.watch(&watcher);
    meal = t.feed(meal);
}

void enable(void) {
	glEnable(GL_DEPTH_TEST); //enable the depth testing
}

void camera(void) {
	glLoadIdentity();

	gluLookAt(xpos, ypos, zpos, 0, 0, 0, 0, 1, 0);

	//glRotatef(180*xrot/800.0, 0.0, 0.0, 1.0); //rotate our camera on teh x-axis (left and right)
	//glRotatef(cos(360*yrot/600.0), 0.0, 1.0, 0.0); //rotate our camera on the y-axis (up and down)
	//glRotatef(sin(360*yrot/600.0), 1.0, 0.0, 0.0); //rotate our camera on teh x-axis (left and right)

	glTranslated(-xpos, -ypos, -zpos); //translate the screen to the position of our camera
}

void display(void) {
	glClearColor(0.0, 0.0, 0.0, 1.0); //clear the screen to black
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //clear the color buffer and the depth buffer
	camera();
	enable();

	watcher.render();

	glutSwapBuffers(); //swap the buffers
}

void reshape(int w, int h) {
	glViewport(0, 0, (GLsizei) w, (GLsizei) h); //set the viewport to the current window specifications
	glMatrixMode(GL_PROJECTION); //set the matrix to projection
	glLoadIdentity();
	gluPerspective(60, (GLfloat) w / (GLfloat) h, 1.0, 1000.0); //set the perspective (angle of sight, width, height, , depth)
	glMatrixMode(GL_MODELVIEW); //set the matrix back to model
}

void keyboard(unsigned char key, int x, int y) {
	if (key == 'q') {
		xrot += 1;
		if (xrot > 360)
			xrot -= 360;
	}

	if (key == 'z') {
		xrot -= 1;
		if (xrot < -360)
			xrot += 360;
	}

	if (key == 'w') {
		float xrotrad, yrotrad;
		yrotrad = (yrot / 180 * 3.141592654f);
		xrotrad = (xrot / 180 * 3.141592654f);
		xpos += float(sin(yrotrad));
		zpos -= float(cos(yrotrad));
		ypos -= float(sin(xrotrad));
	}

	if (key == 's') {
		float xrotrad, yrotrad;
		yrotrad = (yrot / 180 * 3.141592654f);
		xrotrad = (xrot / 180 * 3.141592654f);
		xpos -= float(sin(yrotrad));
		zpos += float(cos(yrotrad));
		ypos += float(sin(xrotrad));
	}

	if (key == 'd') {
		float yrotrad;
		yrotrad = (yrot / 180 * 3.141592654f);
		xpos += float(cos(yrotrad)) * 0.6;
		zpos += float(sin(yrotrad)) * 0.6;
	}

	if (key == 'a') {
		float yrotrad;
		yrotrad = (yrot / 180 * 3.141592654f);
		xpos -= float(cos(yrotrad)) * 0.6;
		zpos -= float(sin(yrotrad)) * 0.6;
	}

        if( key == 13 ) {
            iterate();
        }

	if (key == 27) {
		exit(0);
	}
}

void mouseMovement(int x, int y) {
	int diffx = x - lastx; //check the difference between the current x and the last x position
	int diffy = y - lasty; //check the difference between the current y and the last y position
	lastx = x; //set lastx to the current x position
	lasty = y; //set lasty to the current y position
	yrot += (float) diffy; //set the xrot to xrot with the addition of the difference in the y position
	xrot += (float) diffx; //set the xrot to yrot with the addition of the difference in the x position
}

int main(int argc, char **argv) {
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH);
	glutInitWindowSize(800, 600);
	glutInitWindowPosition(10, 10);
	glutCreateWindow("Linn Renderer (quick deprecated GL hack)");
	init();
	glutDisplayFunc(display);
	glutIdleFunc(display);
	glutReshapeFunc(reshape);

	glutPassiveMotionFunc(mouseMovement); //check for mouse movement

	glutKeyboardFunc(keyboard);

	glutMainLoop();
	return 0;
}
